;--------------------------------------------------------------------------------
;
; Interface to DebugLog module
;
;--------------------------------------------------------------------------------

		AREA	|ARM$$code|,CODE,READONLY

		[ :LNOT: :DEF: NDEBUG

		GET	hdr/DebugLog

		EXPORT	log_printf


; entry	a1 -> format string
;	a2-a4,arg5... arguments

log_printf	LDR	ip,str_address
		STMFD	sp!,{a2-a4}
		STMFD	sp!,{v1,v2,lr}
		TEQ	ip,#0
		BNE	lpf_inited
		MOV	a4,a1
		SWI	XDebugLog_Addresses
		ADDVS	sp,sp,#8
		LDRVS	pc,[sp],#16	;no DebugLog module
		STR	R0,str_address
		STR	R1,str_workspace
		MOV	a1,a4

lpf_inited	;scan through until we find an argument reference

		ADD	v2,sp,#12
		MOV	v1,a1
lpf_scan	LDRB	a2,[v1],#1
		TEQ	a2,#'%'
		TEQNE	a2,#0
		TEQNE	a2,#10
		BNE	lpf_scan
		SUB	a4,v1,a1
		SUBS	a2,a4,#1
		BLNE	log_text
		LDRB	a2,[v1,#-1]	;reload
		TEQ	a2,#'%'
		LDREQB	a2,[v1],#1
		BNE	lpf_notpar
skip_d1		CMP	a2,#'0'
		RSBCSS	a2,a2,#'9'
		LDRCSB	a2,[v1],#1
		BCS	skip_d1
		TEQ	a2,#'.'
		LDREQB	a2,[v1],#1
		BNE	lpf_par
skip_d2		CMP	a2,#'0'
		RSBCSS	a2,a2,#'9'
		LDRCSB	a2,[v1],#1
		BCS	skip_d2
lpf_par		LDRB	a2,[v1,#-1]	;reload
		ORR	a2,a2,#&20
		TEQ	a2,#'d'
		BEQ	lpf_dec
		TEQ	a2,#'s'
		BEQ	lpf_str
		TEQ	a2,#'c'
		LDREQ	a2,[v2],#4
		BEQ	lpf_char
		TEQ	a2,#'x'
		TEQNE	a2,#'p'
		LDREQ	a1,[v2],#4
		BLEQ	log_hex
		MOV	a1,v1
		B	lpf_scan

lpf_str		LDR	a1,[v2],#4
		LDR	ip,str_workspace
		ADD	lr,pc,#0
		LDR	pc,str_address
		MOV	a1,v1
		B	lpf_scan

lpf_dec		LDR	a1,[v2],#4
		BL	log_decimal
		MOV	a1,v1
		B	lpf_scan

lpf_notpar	TEQ	a2,#10
		BNE	lpf_done
		MOV	a2,#13
lpf_char	STR	a2,[sp,#-4]!
		MOV	a1,sp
		MOV	a2,#1
		BL	log_text	; efficient! :-)
		LDR	a2,[sp],#4
		MOV	a1,v1
		B	lpf_scan

lpf_done	LDMFD	sp!,{v1,v2,lr}
		ADD	sp,sp,#12
		MOV	a1,#0		;hope nobody really wants the length!
		MOV	pc,lr


; entry	a1 = number

log_decimal	STR	lr,[sp,#-4]!
		SUB	sp,sp,#12
		MOVS	a2,a1
		MOV	a1,sp
		MOVMI	a3,#'-'
		STRMIB	a3,[a1],#1
		RSBMI	a2,a2,#0
		BL	itoa
		MOV	a1,sp
		LDR	ip,str_workspace
		ADD	lr,pc,#0
		LDR	pc,str_address
		ADD	sp,sp,#12
		LDR	pc,[sp],#4


; entry	a1 = number

log_hex		STR	lr,[sp,#-4]!
		SUB	sp,sp,#8	;room for ASCII hex
		MOV	a3,#7
		MOV	lr,sp
hex_loop	CMP	a1,#&A0000000
		MOV	a2,a1,LSR #28
		ADDHS	a2,a2,#'A'-('0'+10)
		MOV	a2,a2,LSL #24
		ADD	a2,a2,#'0'<<24
		ORR	a4,a2,a4,LSR #8
		MOV	a1,a1,LSL #4
		TST	a3,#3
		STREQ	a4,[lr],#4
		SUBS	a3,a3,#1
		BPL	hex_loop
		MOV	a1,sp
		MOV	a2,#8
		BL	log_text
		ADD	sp,sp,#8
		LDR	pc,[sp],#4


; entry	a1 -> string
;	a2 = length

log_text	ADD	a3,a2,#8	;incl. terminator + sp
		BIC	a3,a3,#3
		MOV	a4,sp
		STR	a4,[sp,-a3]!
		ADD	a4,sp,#4
lgt_copy	SUBS	a2,a2,#1
		LDRPLB	a3,[a1],#1
		MOVMI	a3,#0
		STRB	a3,[a4],#1
		BPL	lgt_copy
		MOV	a4,lr
		ADD	a1,sp,#4
		LDR	ip,str_workspace
		ADD	lr,pc,#0
		LDR	pc,str_address
		LDR	sp,[sp]
		MOV	pc,a4

;
; Convert a 32-bit binary number to an ASCII decimal number
;
; entry	a1 -> buffer (assumed to be sufficiently large)
;	a2 = integer

itoa		ROUT
		MOV	a4,#0
		MOV	a3,#10
00		CMP	a3,a2
		ADDLS	a4,a4,#1		;one more digit
		MOVLS	a3,a3,LSL #1		;x2
		ADDLSS	a3,a3,a3,LSL #2	;x10
		BCC	%00

		ADR	ip,dec_table
		ADD	ip,ip,a4,LSL #2

collp		LDR	a3,[ip],#-4
		MOV	a4,#'0'
divlp		SUBS	a2,a2,a3
		ADDHS	a4,a4,#1
		BHI	divlp
		ADDLO	a2,a2,a3	;restore
		STRB	a4,[a1],#1
		CMP	a3,#1
		BHI	collp
		MOV	a4,#0		;terminator
		STRB	a4,[a1],#1
		MOV	pc,lr

dec_table	DCD	1
		DCD	10
		DCD	100
		DCD	1000
		DCD	10000
		DCD	100000
		DCD	1000000
		DCD	10000000
		DCD	100000000
		DCD	1000000000

str_address	DCD	0
str_workspace	DCD	0

		]

		END
